﻿using System;
using System.Collections.Generic;
using TheWorldLibrary.Items;
using System.IO;
using TheWorldLibrary.Skills;
using TheWorldLibrary;
using TheWorldLibrary.Characters;
using Server.Network;
using TheWorldLibrary.Sprites;
using Server.PC;
using System.Windows.Forms;

namespace Server.Manager
{
    class DataManager
    {
        #region Field Region

        static Dictionary<string, ArmorData> armor = new Dictionary<string, ArmorData>();
        static Dictionary<string, WeaponData> weapons = new Dictionary<string, WeaponData>();
        static Dictionary<string, ShieldData> shields = new Dictionary<string, ShieldData>();

        static Dictionary<string, KeyData> keys = new Dictionary<string, KeyData>();
        static Dictionary<string, ChestData> chests = new Dictionary<string, ChestData>();

        static Dictionary<string, EntityData> entities = new Dictionary<string, EntityData>();

        static Dictionary<string, SkillData> skills = new Dictionary<string, SkillData>();

        #endregion

        #region Property Region

        public static Dictionary<string, ArmorData> ArmorData
        {
            get { return armor; }
        }

        public static Dictionary<string, WeaponData> WeaponData
        {
            get { return weapons; }
        }

        public static Dictionary<string, ShieldData> ShieldData
        {
            get { return shields; }
        }

        public static Dictionary<string, EntityData> EntityData
        {
            get { return entities; }
        }

        public static Dictionary<string, ChestData> ChestData
        {
            get { return chests; }
        }

        public static Dictionary<string, KeyData> KeyData
        {
            get { return keys; }
        }

        public static Dictionary<string, SkillData> SkillData
        {
            get { return skills; }
        }

        #endregion

        #region Constructor
        // private constructor
        private DataManager() { }

        // singleton accessor
        static DataManager instance;
        public static DataManager Instance
        {
            get
            {
                if (instance == null)
                    instance = new DataManager();
                return instance;
            }
        }

        #endregion

        #region Players

        public void CreateAccount(string login, string password, int index)
        {
            if (File.Exists(@"Data\Accounts\" + login + ".data"))
            {
                // TODO: Error out and send message
                ServerTcp.Instance.SendAccountError(index, "Account already exists with this name");
                return;
            }

            // save login and password to file with character name
            using (StreamWriter writer = new StreamWriter(File.Open(@"Data\Accounts\" + login + ".data", FileMode.Create)))
            {
                writer.WriteLine(login);
                writer.WriteLine(password);
                writer.Close();
            }

            ServerTcp.Instance.SendRegisterOkay(index);
        }

        public void AccountLogin(string accountName, string password, int index)
        {
            string tempPass = null;

            DirectoryInfo dir = new DirectoryInfo(@"Data\Accounts\");

            if (File.Exists(dir + accountName + ".data"))
            {
                using (StreamReader reader = new StreamReader(dir + accountName + ".data"))
                {
                    tempPass = reader.ReadLine();
                    tempPass = reader.ReadLine();
                }
            }
            else
            {
                ServerTcp.Instance.SendAccountError(index, "Account does not exits.");
                return;
            }

            if (tempPass == password)
            {
                // Everything is okay lets send the list of characters.
                AccountCharacters(index, accountName);
                // Send login okay
                ServerTcp.Instance.SendLoginOk(index);
                
            }
            else
            {
                ServerTcp.Instance.SendAccountError(index, "Password is incorrect");
            }
        }

        public void AccountCharacters(int index, string accountName)
        {
            // TODO: grab all three characters of the account.
            string account;
            string pass;
            int sprite;
            List<string> charNames = new List<string>();
            List<int> spriteNum = new List<int>();

            using (StreamReader reader = new StreamReader(File.OpenRead(@"Data\Accounts\" + accountName + ".data")))
            {
                account = reader.ReadLine();
                pass = reader.ReadLine();

                while (!reader.EndOfStream)
                {
                    account = reader.ReadLine();
                    sprite = Convert.ToInt32(reader.ReadLine());
                    charNames.Add(account);
                    spriteNum.Add(sprite);
                }
            }

            ServerTcp.Instance.SendCharacterList(index, charNames, spriteNum);
        }       

        public void CreateCharacter(string accountName, string name, int spriteNum, EntityType type, EntityGender gender, int index)
        {
            if (File.Exists(@"Data\Character\" + name + ".xml"))
            {
                ServerTcp.Instance.SendAccountError(index, "Character already exsists with that name");
                return;
            }

            Dictionary<AnimationKey, Animation> animations = new Dictionary<AnimationKey, Animation>();

            Animation animation = new Animation(3, 32, 32, 0, 0);
            animations.Add(AnimationKey.Down, animation);

            animation = new Animation(3, 32, 32, 0, 32);
            animations.Add(AnimationKey.Left, animation);

            animation = new Animation(3, 32, 32, 0, 64);
            animations.Add(AnimationKey.Right, animation);

            animation = new Animation(3, 32, 32, 0, 96);
            animations.Add(AnimationKey.Up, animation);

            AnimatedSprite sprite = new AnimatedSprite(
               null,
               animations);

            Entity entity = new Entity(
                name,
                spriteNum,
                DataManager.EntityData["Fighter"],
                gender,
                type
                );

            foreach (string s in SkillData.Keys)
            {
                Skill skill = Skill.FromSkillData(SkillData[s]);
                entity.Skills.Add(s, skill);
            }

            Character newChar = new Character(entity, sprite);

            Player.Instance.Players[index] = newChar;

            SavePlayer(accountName, index);

            using (StreamWriter writer = new StreamWriter(File.Open(@"Data\Accounts\" + accountName + ".data", FileMode.Append)))
            {
                writer.WriteLine(name);
                writer.WriteLine(spriteNum);
                writer.Close();
            }

            // JoinGame
            Player.Instance.JoinGame(index);
            //Send Player to everyone.
            ServerTcp.Instance.SendJoinMap(index);
        }

        public void LoadPlayer(string name, int index)
        {
            // find character name then add info to Player list
            try
            {
                Player.Instance.Players[index] = XNASerializer.Deserialize<Character>(Application.StartupPath + @"\Data\Character\" + name + ".xml");
                Player.Instance.JoinGame(index);

            }
            catch (Exception ex)
            {
                ServerTcp.Instance.SendAccountError(index, "Unable to find character!");
                Console.Write(ex.Message);
            }
        }

        public void SavePlayer(string name, int index)
        {
            // Lets save the Character Data!
            XNASerializer.Serialize<Character>(@"Data\Character\" + name + ".xml", Player.Instance.Players[index]);
        }

        #endregion

        #region Load Data

        public void ReadEntityData()
        {
            string[] filenames = Directory.GetFiles(@"Data\Classes", "*.xml");

            foreach (string name in filenames)
            {
                string filename = @"Data\Classes\" + Path.GetFileName(name);
                EntityData data = XNASerializer.Deserialize<EntityData>(filename);
                EntityData.Add(data.EntityName, data);
            }
        }

        public void ReadArmorData()
        {
            string[] filenames = Directory.GetFiles(@"Data\Items\Armor", "*.xml");

            foreach (string name in filenames)
            {
                string filename = @"Data\Items\Armor\" + Path.GetFileName(name);
                ArmorData data = XNASerializer.Deserialize<ArmorData>(filename);
                ArmorData.Add(data.Name, data);
            }
        }

        public void ReadWeaponData()
        {
            string[] filenames = Directory.GetFiles(@"Data\Items\Weapon", "*.xml");

            foreach (string name in filenames)
            {
                string filename = @"Data\Items\Weapon\" + Path.GetFileName(name);
                WeaponData data = XNASerializer.Deserialize<WeaponData>(filename);
                WeaponData.Add(data.Name, data);
            }
        }

        public void ReadShieldData()
        {
            string[] filenames = Directory.GetFiles(@"Data\Items\Shield", "*.xml");

            foreach (string name in filenames)
            {
                string filename = @"Data\Items\Shield\" + Path.GetFileName(name);
                ShieldData data = XNASerializer.Deserialize<ShieldData>(filename);
                ShieldData.Add(data.Name, data);
            }
        }

        public void ReadKeyData()
        {
            string[] filenames = Directory.GetFiles(@"Data\Keys", "*.xml");

            foreach (string name in filenames)
            {
                string filename = @"Data\Keys\" + Path.GetFileName(name);
                KeyData data = XNASerializer.Deserialize<KeyData>(filename);
                KeyData.Add(data.Name, data);
            }
        }

        public void ReadChestData()
        {
            string[] filenames = Directory.GetFiles(@"Data\Chests", "*.xml");

            foreach (string name in filenames)
            {
                string filename = @"Data\Chests\" + Path.GetFileName(name);
                ChestData data = XNASerializer.Deserialize<ChestData>(filename);
                ChestData.Add(data.Name, data);
            }
        }

        public void ReadSkillData()
        {
            string[] filenames = Directory.GetFiles(@"Data\Skills", "*.xml");

            foreach (string name in filenames)
            {
                string filename = @"Data\Skills\" + Path.GetFileName(name);
                SkillData data = XNASerializer.Deserialize<SkillData>(filename);
                SkillData.Add(data.Name, data);
            }
        }

        #endregion
    }
}
